package nimbus.commands
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	
	import nimbus.errors.ErrorLog;
	
	/**
	 * Dispatched when the command execution is completed, and the asynchronous
	 * action performed by the command was completed successfully. ("Successfully"
	 * meaning that it performed any loading or other async. actions. You may
	 * not have received the results you wanted or expected.)
	 * 
	 * @eventType flash.events.Event
	 * @see	#dispatchExecutionComplete()
	 */
	[Event(name="executionComplete", type="nimbus.commands.AsyncCommand")]
	
	/**
	 * Dispatched when the command execution is completed, but with errors. This differs from the
	 * <code>EXECUTION_COMPLETE</code> event in that while the command was executed,
	 * the asynchronous action to be performed by the command did not execute
	 * successfully. The failure may be due to connectivity issues, user-interaction, etc.
	 * 
	 * @eventType flash.events.Event
	 * @see	#dispatchExecutionComplete()
	 */
	[Event(name="executionCanceled", type="nimbus.commands.AsyncCommand")]
	
	/**
	 * An abstract command class that supports Asynchronous commands through dispatching
	 * the ExecutionComplete event upon completion of the commands processing.
	 */
	public class AsyncCommand extends EventDispatcher implements ICommand
	{
		/**
		 * Event dispatched when command execution is complete.
		 */
		public static const EXECUTION_COMPLETE:String = "executionComplete";
		
		/**
		 * Event dispatched when command execution is complete, but with errors. 
		 */		
		public static const EXECUTION_CANCELED:String = "executionCanceled";
		
		/**
		 * A brief summary of what the current command is doing. For example, in a new project
		 * command the message might be: "Creating a new Project". 
		 */		
		public var message:String = null;
		
		public function AsyncCommand()
		{
			ErrorLog.testAbstractInstantiation(this, AsyncCommand);
		}
		
		/**
		 * Used to execute the command. All commands should implement this method, and override it.
		 * If the <code>execute()</code> is not overridden, an error will be thrown.
		 * <p>When overriding the method, do not call <code>super.execute()</code>, as doing so
		 * will throw an error.</p>
		 */
		public function execute():void
		{
			ErrorLog.testAbstractMethodCall(this, "execute");
		}
		
		/**
		 * To be called when the asynchronous action has been completed, and is used to notify
		 * any listeners that the command has completed.
		 * 
		 * <p>Two possible events are dispatched by this method: <code>AsyncCommand.EXECUTION_COMPLETE</code>
		 * and <code>AsyncCommand.EXECUTION_CANCELED</code>, signifying that the asynchronous action
		 * was allowed to complete successfully, or was cancelled, either by a failure,
		 * or user-interaction.</p>
		 * 
		 * @param canceled	If <code>true</code> causes an <code>EXECUTION_CANCELED</code> event
		 * 					to be dispatched. 
		 * 
		 */		 
		protected function dispatchExecutionComplete(canceled:Boolean = false):void
		{
			if (canceled)
				dispatchEvent(new Event(EXECUTION_CANCELED));
			else
				dispatchEvent(new Event(EXECUTION_COMPLETE));
		}
		
	}
}
